

-- Namespace
	local _,mod = ...


-- Object cache
	local units = mod.units
	--[[
		{
			[unit] = {
				filter = { btnN..., order='' },
			},
		}
	--]]


-- Static locals
	local NOW
	local inf = math.huge


-- Sorting
	local sort_funcs = {
		time_asc = function(a,b)
			a,b = a[7],b[7]
			if a == 0 then
				a = inf
			end
			if b == 0 then
				b = inf
			end
			return a < b
		end,
		time_desc = function(a,b)
			a,b = a[7],b[7]
			if a == 0 then
				a = inf
			end
			if b == 0 then
				b = inf
			end
			return a > b
		end,
		id_asc = function(a,b)
			return a[1] < b[1]
		end,
		id_desc = function(a,b)
			return a[1] > b[1]
		end,
		name_asc = function(a,b)
			return a[2] < b[2]
		end,
		name_desc = function(a,b)
			return a[2] > b[2]
		end,
	}


-- Table recycle
	local gettbl,deltbl
	do
		local bin = setmetatable({},{ __mode = 'kv' })
		
		function gettbl()
			local t = bin[#bin]
			if t then
				bin[#bin] = nil
			else
				t = {}
			end
			return t
		end
		
		function deltbl(t)
			wipe(t)
			bin[#bin+1] = t
		end
	end


-- Auras changed
	local function populate(i,...)
		local t = gettbl()
		t[1] = i
		for i = 1,select('#',...) do
			t[i+1] = select(i,...)
		end
		return t
	end
	
	local function UNIT_AURA(unit)
		local u = units[unit]
		if not u then return end
		
		NOW = GetTime()
		
		local auras,sortf
		local spell,_,icon,count,dtype,startT,endT,caster,steal,_,spid,canapp,isboss,_1,_2,_3
		
		for filter,btndata in pairs(u) do
			auras = gettbl()
			for i = 1,40 do
				spell,_,icon,count,dtype,startT,endT,caster,steal,_,spid,canapp,isboss,_1,_2,_3 = UnitAura(unit,i,filter)
				if spell then
					if not endT then endT = 0 end
					if not startT then startT = 0 end
					startT = endT - startT
					auras[i] = populate(i,spell,icon,count,dtype,startT,endT,caster,steal,spid,canapp,isboss,_1,_2,_3)
				else
					break
				end
			end
			sortf = sort_funcs[btndata.order]
			if sortf then
				table.sort(auras,sortf)
			end
			for i = 1,#btndata do
				if auras[i] then
					btndata[i]:Show()
					btndata[i]:Update('aura',unpack(auras[i],2,15))
				else
					btndata[i]:Hide()
					btndata[i]:Update('aura',nil)
				end
			end
			for i = 1,#auras do
				deltbl(auras[i])
			end
			deltbl(auras)
		end
	end
	
	mod:event_register('UNIT_AURA',UNIT_AURA)
	
	mod:event_register('PLAYER_TARGET_CHANGED',function()
		UNIT_AURA('target')
		UNIT_AURA('targettarget')
	end)
	
	mod:event_register('PLAYER_FOCUS_CHANGED',function()
		UNIT_AURA('focus')
		UNIT_AURA('focustarget')
	end)
	
	mod:event_register('PLAYER_ENTERING_WORLD',function()
		for unit in pairs(units) do
			UNIT_AURA(unit)
		end
	end)
	
	mod:event_register('ZONE_CHANGED_NEW_AREA',function()
		-- Fix a bug where exiting an instance mid-combat will cause auras to stick.
		for unit in pairs(units) do
			UNIT_AURA(unit)
		end
	end)
